#include "stdafx.h"
#include "CppUnitTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace NativeTest_Question34
{

	class MyStack
	{
	public:
		MyStack();
		~MyStack();
		bool empty();
		int top();
		int size();
		void push(int val);
		void pop();
	private:
		int* data;
		int index;
	};

	MyStack::MyStack()
	{
		data = new int[10];
		index = -1;
	}

	MyStack::~MyStack()
	{
		//delete[] data;
	}
	bool MyStack::empty()
	{
		return index == -1;
	}
	int MyStack::top()
	{
		if(!empty())
			return this->data[index];
		else
			return INT_MIN;
	}
	int MyStack::size()
	{
		return index + 1;
	}
	void MyStack::push(int val)
	{
		this->data[++index] =val;
	}
	void MyStack::pop()
	{
		if(!empty())
			index--;
	}
	


	class MyQueue
	{
	public:
		MyQueue();
		~MyQueue();
		void enqueue(int val);
		void dequeue();
		int first();
		int last();
		int size();
		bool empty();

	private:
		void move(MyStack& from , MyStack& to);
		MyStack in ;
		MyStack out;
	};

	MyQueue::MyQueue()
	{
		in = MyStack();
		out = MyStack();
	}

	MyQueue::~MyQueue()
	{
	}
	void MyQueue::dequeue()
	{
		if(out.empty() && !in.empty())
			move(in, out);

		if(!out.empty())
			out.pop();
	}
	void MyQueue::enqueue(int val)
	{
		in.push(val);
	}
	
	int MyQueue::first()
	{
		if(out.empty() && !in.empty())
			move(in, out);
		if(!out.empty())
			return out.top();
		else
			return INT_MIN;
	}

	int MyQueue::last()
	{
		if(in.empty() &&  !out.empty())
			move(out, in);
		if(!in.empty())
			return in.top();
		else
			return INT_MIN;
	}

	bool MyQueue::empty()
	{
		return in.empty() && out.empty();
	}

	int MyQueue::size()
	{
		return in.size() + out.size();
	}
	
	void MyQueue::move(MyStack& from , MyStack& to)
	{
		while(!from.empty())
		{
			to.push(from.top());
			from.pop();
		}
	}
}
namespace NativeTest
{
	using namespace NativeTest_Question34;
	TEST_CLASS(Question34)
	{
	public:
		
		TEST_METHOD(Question34_TestMethod1)
		{
			MyStack s;
			Assert::IsTrue(s.empty());
			Assert::AreEqual(0, s.size());

			s.push(1);
			Assert::IsFalse(s.empty());
			Assert::AreEqual(1, s.size());

			s.push(2); Assert::AreEqual(2, s.size());
			s.push(3); Assert::AreEqual(3, s.size());

			Assert::AreEqual(3, s.top());
			s.pop(); Assert::AreEqual(2, s.size());

			
			Assert::AreEqual(2, s.top());
			s.pop(); Assert::AreEqual(1, s.size());

			s.pop(); Assert::AreEqual(0, s.size());
			s.pop(); Assert::AreEqual(0, s.size());

			MyQueue q;
			Assert::IsTrue(q.empty());
			Assert::AreEqual(INT_MIN, q.first());
			Assert::AreEqual(INT_MIN, q.last());

			q.enqueue(1); 
			Assert::AreEqual(1, q.first());
			Assert::AreEqual(1, q.last());
			Assert::AreEqual(1, q.size());

			q.enqueue(2);
			Assert::AreEqual(1, q.first());
			Assert::AreEqual(2, q.last());
			Assert::AreEqual(2, q.size());

			q.enqueue(3);
			Assert::AreEqual(1, q.first());
			Assert::AreEqual(3, q.last());
			Assert::AreEqual(3, q.size());


			q.dequeue();
			Assert::AreEqual(2, q.first());
			Assert::AreEqual(3, q.last());
			Assert::AreEqual(2, q.size());

			q.dequeue();
			Assert::AreEqual(3, q.first());
			Assert::AreEqual(3, q.last());
			Assert::AreEqual(1, q.size());


			q.dequeue();
			Assert::AreEqual(INT_MIN, q.first());
			Assert::AreEqual(INT_MIN, q.last());
			Assert::AreEqual(0, q.size());
		}

	};
}